﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Linq.Expressions;

namespace Petaframe.DataAccess
{
    class PropertyAccessor<T>
    {
        private Dictionary<string, Func<T, object>> propAccessors = new Dictionary<string, Func<T, object>>();
 
      public PropertyAccessor()
      {
         Type type = typeof (T);
 
         foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Public | BindingFlags.GetProperty 
            | BindingFlags.Instance))
         {
            if (!pi.CanRead)
               continue;
 
            ParameterExpression parameter = Expression.Parameter(type, "r");
 
            Expression<Func<T, object>> lambda;
            
            if (pi.PropertyType.IsValueType)
            {
               lambda = Expression.Lambda<Func<T, object>>(
                  Expression.TypeAs(Expression.Property(parameter, pi.Name), typeof(object)), parameter);
            }
            else
            {
               lambda = Expression.Lambda<Func<T, object>>(Expression.Property(parameter, pi.Name), parameter);
            }
 
            propAccessors.Add(pi.Name, lambda.Compile());
         }
      }
 
      public object Get(T obj, string propName)
      {
         return propAccessors[propName](obj);
      }
    }
}
